import axios from 'axios'
import type { AxiosInstance } from 'axios'
import type { SyRequestConfig } from './type'

class SyRequest {
  instance: AxiosInstance
  constructor(pubConfig: any) {
    this.instance = axios.create(pubConfig)
    // 这是每个人请求都会经过的全局拦截器
    this.instance.interceptors.request.use(
      (config) => {
        return config
      },
      (err) => {
        return err
      }
    )
    this.instance.interceptors.response.use(
      (res) => {
        console.log(res.data)
        return res.data //返回的data数据为服务器数据
      },
      (err) => {
        return err
      }
    )
    // 这个是单个实例经过的实例拦截器可设置
    // 顺序先加后执行
    this.instance.interceptors.request.use(
      pubConfig.interceptors?.requestSuccessFn,
      pubConfig.interceptors?.requestFailFn
    )
    // 顺序是先加先执行
    this.instance.interceptors.response.use(
      pubConfig.interceptors?.responseSuccessFn,
      pubConfig.interceptors?.responseFailFn
    )
  }
  request<T>(uniConfig: SyRequestConfig<T>) {
    // 单个请求方法拦截器,算属于自己的写的拦截器,不算axios的,原理只是让他流过这个方法
    if (uniConfig.interceptors?.requestSuccessFn) {
      uniConfig = uniConfig.interceptors.requestSuccessFn(uniConfig) //让他走一遍这个函数的,相当于请求拦截了,uniConfig,返回出来的也是uniConfig
    }
    // return this.instance.request(uniConfig) 为什么不直接这个呢,因为还要响应回来的数据也要拦截一下所以用到promise,自己封装多一层promise
    return new Promise<T>((resolve, reject) => {
      this.instance
        .request<any, T>(uniConfig)
        .then((res) => {
          if (uniConfig.interceptors?.responseSuccessFn) {
            res = uniConfig.interceptors.responseSuccessFn(res) //让他走一遍这个函数的,相当于响应回来的拦截了,res,返回出来的也是res
          }
          resolve(res)
        })
        .catch((err) => {
          reject(err)
        })
    })
  }
  get<T = any>(uniConfig: SyRequestConfig<T>) {
    return this.request<T>({
      method: 'GET',
      ...uniConfig
    })
  }
  post<T = any>(uniConfig: SyRequestConfig<T>) {
    return this.request<T>({
      method: 'POST',
      ...uniConfig
    })
  }
  patch<T = any>(uniConfig: SyRequestConfig<T>) {
    return this.request<T>({
      method: 'PATCH',
      ...uniConfig
    })
  }
  delete<T = any>(uniConfig: SyRequestConfig<T>) {
    return this.request<T>({
      method: 'DELETE',
      ...uniConfig
    })
  }
}

export default SyRequest
